
// hasErrorInSuccess
// defaultAlert

import type {App} from "vue";
import type {AxiosRequestConfig, AxiosResponse} from "axios";
import {VCairnEvent} from "../vcc/VCairnEvent";
import axios from "axios";


export type HasErrorInSuccess = (response: AxiosResponse) => boolean;
export type ErrorInSuccessHandler = (response: AxiosResponse) => void;
export type DefaultErrorHandler = (error: any) => void;
export type ErrorCodeHandleItem = {
    label?: string,
    desc?: string,
    handler: (code: string|number, response: AxiosResponse) => void,
};

export type VCairnConfig = {
    hasErrorInSuccess?: HasErrorInSuccess,
    errorInSuccessHandler?: ErrorInSuccessHandler,
    defaultErrorHandler?: DefaultErrorHandler,
    axiosConfig: AxiosRequestConfig,
    specifiedErrorCodes?: Record<string|number, ErrorCodeHandleItem>
}

const vCairnConfig:VCairnConfig = {axiosConfig: {}};

export function useRequest(value?: AxiosRequestConfig) {

    const http = axios.create(value||vCairnConfig.axiosConfig||{});

    async function send(options:AxiosRequestConfig, custom: boolean = false) {
        if (custom) return http(options);
        return http(options).then(defaultSuccessHandler).catch(defaultErrorHandler);
    }

    return {
        send
    }

}

// http code 为 2xx
function defaultSuccessHandler(response: AxiosResponse) {
    return !vCairnConfig.hasErrorInSuccess!(response) ? (response.data || {}) : vCairnConfig.errorInSuccessHandler!(response);
}

// http code 为非2xx
function defaultErrorHandler(error: any) {
    if (error.response) {
        vCairnConfig.errorInSuccessHandler!(error.response);
    } else {
        console.log('defaultErrorHandler', error.toJSON());
        vCairnConfig.defaultErrorHandler!(error);
    }
}

function hasErrorInSuccess(response: AxiosResponse) {
    const responseData = response.data;
    return responseData?.code !== '000000';
}
function errorInSuccessHandler(response: AxiosResponse) {
    const respondData = response.data;
    try {
        const specifiedCodes = vCairnConfig.specifiedErrorCodes || {};
        const code = respondData.code.toString() as keyof typeof specifiedCodes;
        const codeHandleItem = specifiedCodes[code];
        if (codeHandleItem) {
            if (codeHandleItem.handler) {
                codeHandleItem.handler(code, response);
            } else {
                new VCairnEvent(VCairnEvent.ERROR_CODE, [code, response]).emit();
            }
        } else {
            new VCairnEvent(VCairnEvent.ERROR_CODE, [code, response]).emit();
        }
    } catch(error:any) {
        vCairnConfig.defaultErrorHandler!(error);
    }
}

export default {
    install: (app:App, options?: VCairnConfig) => {
        Object.assign(vCairnConfig, options || {});
        vCairnConfig.hasErrorInSuccess = options?.hasErrorInSuccess || hasErrorInSuccess;
        vCairnConfig.defaultErrorHandler = options?.defaultErrorHandler || defaultErrorHandler;
        vCairnConfig.errorInSuccessHandler = options?.errorInSuccessHandler || errorInSuccessHandler;
        vCairnConfig.axiosConfig = options?.axiosConfig || {};
        vCairnConfig.specifiedErrorCodes = options?.specifiedErrorCodes || {};
    }
}

